#include "DetectorConstruction.hh"
#include "DetectorSD.hh"

#include "G4Material.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4LogicalVolume.hh"
#include "G4ThreeVector.hh"
#include "G4PVPlacement.hh"
#include "G4RotationMatrix.hh"
#include "G4NistManager.hh"
#include "globals.hh"
#include "G4VisAttributes.hh" 
#include "G4SDManager.hh"

DetectorConstruction::DetectorConstruction() {}

DetectorConstruction::~DetectorConstruction() {}

G4VPhysicalVolume* DetectorConstruction::Construct()
{
  // --- materials ---
  // создаем материалы
  // первый способ:
  //Les matériaux de construction 1ère méthode:
  G4Element* N = new G4Element("Nitrogen", "N", 7, 14.01*g/mole);
  G4Element* O = new G4Element("Oxygen"  , "O", 8, 16.00*g/mole);
  G4Material* Air = new G4Material("Air", 1.29*mg/cm3, 2);
  Air->AddElement(N, 70*perCent);
  Air->AddElement(O, 30*perCent);
  
  // второй способ: использует встроенную в Geant4 базу материалов
  // более простой, но иногда приходится прибегать к первому способу,
  // т.к. не все материалы содержатся в базе
//Deuxième méthode: en utilisantla construction des matériaux de base Geant4
//Plus facile, mais parfois on doit recourir à la première méthode,
//Parce que tous les matériaux ne sont pas définis dans la base de données.
  G4NistManager* nistMan = G4NistManager::Instance();
  //G4Material* Air = nistMan->FindOrBuildMaterial("G4_AIR");
  G4Material* saMaterial = nistMan->FindOrBuildMaterial("G4_Al");
  G4Material* detMaterial = nistMan->FindOrBuildMaterial("G4_SODIUM_IODIDE");

  // --- volumes ---
  // создаем геометрию
  //Construire la géométrie
  G4double saSize = 3*cm; // размер образца			taille de l'échantillon	
  G4double saThick = 0.5*mm; // толщина образца		épaisseur
  G4double detDiam = 3*cm; // диаметр детектора			diamètre du détecteur
  G4double detThick = 4*cm; // толщина детектора		épaisseur
  G4double gap1 = 5*mm; // расстояние от источника до образца		distance source échantillon
  G4double gap2 = 25*mm; // расстояние от образца до детектора		distance échantillon détecteur

  // мировой объем в виде параллелепипеда
  //Un monde parallélipipédique.
  G4Box* world_box = new G4Box("world", (saSize + detDiam)/2 + 1*cm, (saSize + detDiam)/2 + 1*cm, gap1 + gap2 + detThick/2 + 1*cm);
  // заполняем его воздухом
  //Rempli d'air
  G4LogicalVolume* world_log = new G4LogicalVolume(world_box, Air, "world");
  // и помещаем в начало координат
  //Définition de l'origine des coordonnées
  G4VPhysicalVolume* world_phys = new G4PVPlacement(0, G4ThreeVector(), world_log, "world", 0, false, 0);

  // образец	échantillon
  G4Box* sample_box = new G4Box("sample", saSize/2, saSize/2, saThick/2);
  G4LogicalVolume* sample_log = new G4LogicalVolume(sample_box, saMaterial, "sample");
  // помещаем его в мировой объем со смещением на gap1
  //Placé dans le monde à une distance gap1
  G4VPhysicalVolume* sample_phys = new G4PVPlacement(0, G4ThreeVector(0, 0, gap1), sample_log, "sample", world_log, false, 0);

  // детектор в виде цилиндра
  //Un détecteur cylindrique
  G4Tubs* det_tube = new G4Tubs("detector", 0, detDiam/2, detThick/2, 0, 360*deg);
  G4LogicalVolume* det_log = new G4LogicalVolume(det_tube, detMaterial, "detector");
  // помещаем его в мировой объем со смещением на gap1+gap2
  //Placé à la distance du centre du monde à gap1+gap2
  G4VPhysicalVolume* det_phys = new G4PVPlacement(0, G4ThreeVector(0, 0, gap1 + gap2), det_log, "detector", world_log, false, 0);
  
  // --- sensitive detectors ---
  // регистрируем det_log как детектор
  // теперь при прохождении частиц через этот объем будет вызываться
  // метод DetectorSD::ProcessHits() в котором мы будем регистрировать
  // энергию оставленную в детекторе

//Enregistrement comme détecteur det_log
//Au passage  de particules par le centre seront appelés
//Méthode DetectorSD:: ProcessHits () où l'on enregistrera
//L'énergie déposée dans le détecteur
  DetectorSD* detectorSD = new DetectorSD("DetectorSD");
  G4SDManager* sdMan = G4SDManager::GetSDMpointer();
  sdMan->AddNewDetector(detectorSD);
  det_log->SetSensitiveDetector(detectorSD);
  
  // --- visualisation ---
  // отключаем отображение мирового объема
  //Désactiver l'affichage du monde
  world_log->SetVisAttributes(G4VisAttributes::Invisible);
  // а для образца и детектора задаем цвета отображения
  // (по умолчанию все элементы геометрии окрашены в серый цвет)
  //Pour l'échantillon et le détecteur, demander des couleurs (défaut = gris)
  sample_log->SetVisAttributes(G4VisAttributes::G4VisAttributes(G4Colour::Yellow()));
  det_log->SetVisAttributes(G4VisAttributes::G4VisAttributes(G4Colour::Blue()));

  // возвращаем указатель на мировой объем
  //Retourne un pointeur vers la monde
  return world_phys;
}

